#include <stdafx.h>
#include "VcServerUtils.h"

rdc_transport::HandleGuard rdc_transport::OpenChannel(std::string& name)
{
    assert(name.size() <=7);

    HANDLE hChannel = ::WTSVirtualChannelOpen(
        WTS_CURRENT_SERVER_HANDLE,
        WTS_CURRENT_SESSION,
        const_cast<char*>(name.c_str())
        );

    if (hChannel == NULL)
        throw std::runtime_error(std::string(__FUNCTION__) + " Error: WTSVirtualChannelOpen failed " + utils::FormatLastError());
    
    return HandleGuard(hChannel, ::WTSVirtualChannelClose);
}

void rdc_transport::GetChannelFile(HANDLE& file, HANDLE connection)
{
    // Get channel file handle
    PVOID vcFileHandlePtr = NULL;
    DWORD dwFileHandlePtrLen;

    BOOL bRes = ::WTSVirtualChannelQuery(
        connection,
        WTSVirtualFileHandle,
        &vcFileHandlePtr,
        &dwFileHandlePtrLen);

    if (bRes == FALSE)
        throw std::runtime_error(std::string(__FUNCTION__) + " Error: WTSVirtualChannel failed " + utils::FormatLastError());

    if (dwFileHandlePtrLen != sizeof(HANDLE))
        throw std::runtime_error(std::string(__FUNCTION__) + " Unexpected Error: wrong handle length");

    boost::shared_ptr<void> guard(vcFileHandlePtr, ::WTSFreeMemory);

    memcpy(&file, vcFileHandlePtr, sizeof(file));
}

bool rdc_transport::ChannelDoesExist(const char* szChannelName)
{
    assert(::strlen(szChannelName)<=7);

    bool ret = false;
    DWORD dwSessionId = 0;

    if (::ProcessIdToSessionId(::GetCurrentProcessId(), &dwSessionId) == FALSE)        
        return ret;

    HANDLE hChannel = ::WTSVirtualChannelOpen(
        WTS_CURRENT_SERVER_HANDLE,
        dwSessionId,
        const_cast<LPSTR>(szChannelName));

    if (hChannel == NULL)
        return ret;

    if (!::WTSVirtualChannelPurgeOutput(hChannel))
    {
        DWORD err = ::GetLastError();

        if (ERROR_INVALID_FUNCTION != err)
            ret = true;
    }
    else 
        ret = true;

    if (hChannel != NULL)
        ::WTSVirtualChannelClose(hChannel);

    return ret;
}